package com.roy.hystrix;

import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

import rx.Observable;
import rx.functions.Action1;

public class HelloMain {
	private static Logger logger = LoggerFactory.getLogger(HelloMain.class);

	public static void main(String[] args) throws Exception {
		//重写了getCacheKey()方法，需要初始化HystrixRequestContext。在SpringCloud中会通过filter完成初始化。
		HystrixRequestContext.initializeContext();
		// hystrix以command形式执行，每个Command只能执行一次。
		// log日志中会打印出hystrix的配置信息
		// 1、同步执行
		HelloCommand command1 = new HelloCommand("word");
		logger.info(command1.execute());
		// 2、异步执行
		HelloCommand command2 = new HelloCommand("bob");
		Future<String> queue = command2.queue();
		logger.info(queue.get());
		// 3、observer方式执行，需要订阅执行
		Observable<String> observer1 = new HelloCommand("World").observe();
		observer1.subscribe(new Action1<String>() {
			public void call(String t) {
				logger.info("call : " + t);
			}
		});
		//4、请求缓存:根据Command的getCacheKey方法计算缓存key，"重复"的请求直接走缓存。
		//这次不会打印 run 方法中的日志。
		HelloCommand command4 = new HelloCommand("word");
		logger.info(command4.execute());
	}

	static class HelloCommand extends HystrixCommand<String> {

		private String keyWord;
		private Boolean isThrowException;

		public HelloCommand(String keyWord) {
			super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
					.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
							.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)//采用信号隔离机制
							.withExecutionIsolationSemaphoreMaxConcurrentRequests(8))//最大信号数8
					);
			System.out.println("====building====");
			this.keyWord = keyWord;
			this.isThrowException = keyWord.equals("true");
		}

		// 执行方法
		@Override
		protected String run() throws Exception {
			System.out.println("计算执行方法。");
			if (isThrowException) {
				throw new RuntimeException("failed");
			} else {
				return "Hello : " + keyWord;
			}
		}

		// 异常隔离：run方法出现异常后，会进入这个方法。而异常不会再往外抛出。
		@Override
		protected String getFallback() {
			return "getFallback";
		}
		//请求缓存：按这个方法重写缓存的key规则。按这个规则，"重复"的请求会从缓存中获取，而不会重新去run
		@Override
		protected String getCacheKey() {
			return this.keyWord;
		}
	}
}
